#include "screen.h"
#include "codeports.h"

void
SCR_Init(void)
{
	printf("Modes:\n");
	for(cp.video.mode.code = 0; cp.video.mode.code < vga_lastmodenumber(); cp.video.mode.code++)
	{
		if(vga_hasmode(cp.video.mode.code))
		{
			cp.video.mode.info = vga_getmodeinfo(cp.video.mode.code);
			printf("\t%i: %dx%d, %d colors\n", cp.video.mode.code, cp.video.mode.info->width, cp.video.mode.info->height, cp.video.mode.info->colors);
		}
	}

	printf("Mode: ");
	scanf("%i", &cp.video.mode.code);
	getchar();

	vga_setmode(cp.video.mode.code);

	gl_setcontextvga(cp.video.mode.code);
	cp.video.mode.screen = gl_allocatecontext();
	gl_getcontext(cp.video.mode.screen);
	gl_enablepageflipping(cp.video.mode.screen);
	gl_setcontext(cp.video.mode.screen);

	switch(cp.video.mode.screen->bytesperpixel)
	{
		case 1:
		{
			gl_setrgbpalette();
			SCR_SetPixelRGB = SCR_SetPixelRGB8;
			SCR_GetPixelRGB = SCR_GetPixelRGB8;
			SCR_SetBoxRGB = SCR_SetBoxRGB8;
			SCR_SetBox = SCR_SetBoxRGB8;
			BOX_SetPixelRGB = BOX_SetPixelRGB8;
			BOX_GetPixelRGB = BOX_GetPixelRGB8;
			break;
		}
		case 2:
		{
			SCR_SetPixelRGB = SCR_SetPixelRGB16;
			SCR_GetPixelRGB = SCR_GetPixelRGB16;
			SCR_SetBoxRGB = SCR_SetBoxRGB16;
			SCR_SetBox = SCR_SetBoxRGB16;
			BOX_SetPixelRGB = BOX_SetPixelRGB16;
			BOX_GetPixelRGB = BOX_GetPixelRGB16;
			break;
		}
		case 3:
		{
			SCR_SetPixelRGB = SCR_SetPixelRGB24;
			SCR_GetPixelRGB = SCR_GetPixelRGB24;
			SCR_SetBoxRGB = SCR_SetBoxRGB24;
			SCR_SetBox = SCR_SetBoxRGB24;
			BOX_SetPixelRGB = BOX_SetPixelRGB24;
			BOX_GetPixelRGB = BOX_GetPixelRGB24;
			break;
		}
		case 4:
		{
			SCR_SetPixelRGB = SCR_SetPixelRGB32;
			SCR_GetPixelRGB = SCR_GetPixelRGB32;
			SCR_SetBoxRGB = SCR_SetBoxRGB32;
			SCR_SetBox = SCR_SetBoxRGB32;
			BOX_SetPixelRGB = BOX_SetPixelRGB32;
			BOX_GetPixelRGB = BOX_GetPixelRGB32;
			break;
		}
	}

	SWP_Init();
}

void
SCR_Final(void)
{
	SWP_Final();

	gl_freecontext(cp.video.mode.screen);

	vga_setmode(TEXT);
}

void
SCR_GetSize(unsigned int *width, unsigned int *height)
{
	*width = cp.video.mode.screen->width;
	*height = cp.video.mode.screen->height;
}

void
SCR_GetDepth(unsigned int *depth)
{
	*depth = cp.video.mode.screen->bytesperpixel;
}

void
SCR_Clear(void)
{
	gl_clearscreen(0);
	/*
	unsigned int i, j;
	for(j = 0; j < cp.video.mode.screen->height; j++)
	{
		for(i = 0; i < cp.video.mode.screen->width; i++)
		{
			switch(cp.video.mode.screen->bytesperpixel)
			{
				case 1:
				{
					//SCR_SetPixelColor(i, j, 0);
					SCR_SetPixelRGB8(i, j, 0, 0, 0);
					break;
				}
				case 2:
				{
					SCR_SetPixelRGB16(i, j, 0, 0, 0);
					break;
				}
				case 3:
				{
					SCR_SetPixelRGB24(i, j, 0, 0, 0);
					break;
				}
				case 4:
				{
					SCR_SetPixelRGBA(i, j, 0, 0, 0, 0);
					break;
				}
			}
		}
	}
	*/
}

void
SCR_Swap(void)
{
	vga_waitretrace();
	gl_copyscreen(cp.video.mode.screen);
	//usleep(10000);
}

void
SCR_SetPixelColor(int x, int y, unsigned char c)
{
	if(0 <= x && x < cp.video.mode.screen->width && 0 <= y && y < cp.video.mode.screen->height)
		gl_setpixel(x, y, c);
}

void
SCR_SetPixelRGB8(int x, int y, unsigned char r, unsigned char g, unsigned char b)
{
	if(0 <= x && x < cp.video.mode.screen->width && 0 <= y && y < cp.video.mode.screen->height)
		gl_setpixelrgb(x, y, r, g, b);
}

void
SCR_SetPixelRGB16(int x, int y, unsigned char r, unsigned char g, unsigned char b)
{
	if(0 <= x && x < cp.video.mode.screen->width && 0 <= y && y < cp.video.mode.screen->height)
		gl_setpixelrgb(x, y, r, g, b);
}

void
SCR_SetPixelRGB24(int x, int y, unsigned char r, unsigned char g, unsigned char b)
{
	if(0 <= x && x < cp.video.mode.screen->width && 0 <= y && y < cp.video.mode.screen->height)
		gl_setpixelrgb(x, y, r, g, b);
}

void
SCR_SetPixelRGB32(int x, int y, unsigned char r, unsigned char g, unsigned char b)
{
	if(0 <= x && x < cp.video.mode.screen->width && 0 <= y && y < cp.video.mode.screen->height)
		gl_setpixelrgb(x, y, r, g, b);
}

void
SCR_SetPixelRGBA(int x, int y, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
	if(0 <= x && x < cp.video.mode.screen->width && 0 <= y && y < cp.video.mode.screen->height)
		gl_setpixelrgb(x, y, r, g, b);
}

void
SCR_GetPixelColor(int x, int y, unsigned char *c)
{
	if(0 <= x && x < cp.video.mode.screen->width && 0 <= y && y < cp.video.mode.screen->height)
		*c = gl_getpixel(x, y);
}

void
SCR_GetPixelRGB8(int x, int y, unsigned char *r, unsigned char *g, unsigned char *b)
{
	if(0 <= x && x < cp.video.mode.screen->width && 0 <= y && y < cp.video.mode.screen->height)
	{
		// Reports Red Only on 320x240x256 (6), Issues on SVGALIB Planar Modes
		// gl_getpixelrgb(x, y, (int *) r, (int *) g, (int *) b);
		unsigned char c = gl_getpixel(x, y);
		*r = ((c & 0xC0) >> 6) << 6;
		*g = ((c & 0x38) >> 3) << 5;
		*b = (c & 0x07) << 5;
	}
}

void
SCR_GetPixelRGB16(int x, int y, unsigned char *r, unsigned char *g, unsigned char *b)
{
	if(0 <= x && x < cp.video.mode.screen->width && 0 <= y && y < cp.video.mode.screen->height)
		gl_getpixelrgb(x, y, (int *) r, (int *) g, (int *) b);
}

void
SCR_GetPixelRGB24(int x, int y, unsigned char *r, unsigned char *g, unsigned char *b)
{
	if(0 <= x && x < cp.video.mode.screen->width && 0 <= y && y < cp.video.mode.screen->height)
		gl_getpixelrgb(x, y, (int *) r, (int *) g, (int *) b);
}

void
SCR_GetPixelRGB32(int x, int y, unsigned char *r, unsigned char *g, unsigned char *b)
{
	if(0 <= x && x < cp.video.mode.screen->width && 0 <= y && y < cp.video.mode.screen->height)
		gl_getpixelrgb(x, y, (int *) r, (int *) g, (int *) b);
}

void
SCR_GetPixelRGBA(int x, int y, unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *a)
{
	if(0 <= x && x < cp.video.mode.screen->width && 0 <= y && y < cp.video.mode.screen->height)
		gl_getpixelrgb(x, y, (int *) r, (int *) g, (int *) b);
}

void
SCR_SetBoxColor(int x, int y, BOX *box)
{
	unsigned int i, j;
	unsigned char c;
	for(j = 0; j < box->info.height; j++)
	{
		for(i = 0; i < box->info.width; i++)
		{
			BOX_GetPixelColor(box, i, j, &c);
			SCR_SetPixelColor(x + i, y + j, c);
		}
	}
}

void
SCR_SetBoxRGB8(int x, int y, BOX *box)
{
	unsigned int i, j;
	unsigned char r, g, b;
	for(j = 0; j < box->info.height; j++)
	{
		for(i = 0; i < box->info.width; i++)
		{
			BOX_GetPixelRGB8(box, i, j, &r, &g, &b);
			SCR_SetPixelRGB8(x + i, y + j, r, g, b);
		}
	}
}

void
SCR_SetBoxRGB16(int x, int y, BOX *box)
{
	unsigned int i, j;
	unsigned char r, g, b;
	for(j = 0; j < box->info.height; j++)
	{
		for(i = 0; i < box->info.width; i++)
		{
			BOX_GetPixelRGB16(box, i, j, &r, &g, &b);
			SCR_SetPixelRGB16(x + i, y + j, r, g, b);
		}
	}
}

void
SCR_SetBoxRGB24(int x, int y, BOX *box)
{
	unsigned int i, j;
	unsigned char r, g, b;
	for(j = 0; j < box->info.height; j++)
	{
		for(i = 0; i < box->info.width; i++)
		{
			BOX_GetPixelRGB24(box, i, j, &r, &g, &b);
			SCR_SetPixelRGB24(x + i, y + j, r, g, b);
		}
	}
}

void
SCR_SetBoxRGB32(int x, int y, BOX *box)
{
	unsigned int i, j;
	unsigned char r, g, b;
	for(j = 0; j < box->info.height; j++)
	{
		for(i = 0; i < box->info.width; i++)
		{
			BOX_GetPixelRGB32(box, i, j, &r, &g, &b);
			SCR_SetPixelRGB32(x + i, y + j, r, g, b);
		}
	}
}

void
SCR_SetBoxRGBA(int x, int y, BOX *box)
{
	unsigned int i, j;
	unsigned char r, g, b, a;
	for(j = 0; j < box->info.height; j++)
	{
		for(i = 0; i < box->info.width; i++)
		{
			BOX_GetPixelRGBA(box, i, j, &r, &g, &b, &a);
			SCR_SetPixelRGBA(x + i, y + j, r, g, b, a);
		}
	}
}

void
SCR_SetImage(char *image)
{
	MagickWand *mw;
	unsigned char *buffer;
	unsigned int i, j;
	buffer = malloc(cp.video.mode.screen->width * cp.video.mode.screen->height * 4);
	mw = NewMagickWand();
	MagickReadImage(mw, image);
	if(cp.video.mode.screen->width != MagickGetImageWidth(mw) || cp.video.mode.screen->height != MagickGetImageHeight(mw))
		MagickScaleImage(mw, cp.video.mode.screen->width, cp.video.mode.screen->height);
	MagickExportImagePixels(mw, 0, 0, cp.video.mode.screen->width, cp.video.mode.screen->height, "RGBO", CharPixel, buffer);
	DestroyMagickWand(mw);
	for(j = 0; j < cp.video.mode.screen->height; j++)
	{
		for(i = 0; i < cp.video.mode.screen->width; i++)
		{
			switch(cp.video.mode.screen->bytesperpixel)
			{
				case 1:
				{
					//SCR_SetPixelColor(i, j, buffer[(j * cp.video.mode.screen->width + i) * 4]);
					SCR_SetPixelRGB8(i, j, buffer[(j * cp.video.mode.screen->width + i) * 4 + 0], buffer[(j * cp.video.mode.screen->width + i) * 4 + 1] , buffer[(j * cp.video.mode.screen->width + i) * 4 + 2]);
					break;
				}
				case 2:
				{
					SCR_SetPixelRGB16(i, j, buffer[(j * cp.video.mode.screen->width + i) * 4 + 0], buffer[(j * cp.video.mode.screen->width + i) * 4 + 1] , buffer[(j * cp.video.mode.screen->width + i) * 4 + 2]);
					break;
				}
				case 3:
				{
					SCR_SetPixelRGB24(i, j, buffer[(j * cp.video.mode.screen->width + i) * 4 + 0], buffer[(j * cp.video.mode.screen->width + i) * 4 + 1] , buffer[(j * cp.video.mode.screen->width + i) * 4 + 2]);
					break;
				}
				case 4:
				{
					SCR_SetPixelRGBA(i, j, buffer[(j * cp.video.mode.screen->width + i) * 4 + 0], buffer[(j * cp.video.mode.screen->width + i) * 4 + 1] , buffer[(j * cp.video.mode.screen->width + i) * 4 + 2], buffer[(j * cp.video.mode.screen->width + i) * 4 + 3]);
					break;
				}
			}
		}
	}
	free(buffer);
}

void
SCR_GetImage(char *image)
{
	MagickWand *mw;
	unsigned char *buffer;
	unsigned int i, j;
	unsigned char /*c,*/ r, g, b, a;
	buffer = malloc(cp.video.mode.screen->width * cp.video.mode.screen->height * 4);
	for(j = 0; j < cp.video.mode.screen->height; j++)
	{
		for(i = 0; i < cp.video.mode.screen->width; i++)
		{
			switch(cp.video.mode.screen->bytesperpixel)
			{
				case 1:
				{
					//SCR_GetPixelColor(i, j, &c);
					SCR_GetPixelRGB8(i, j, &r, &g, &b);
					buffer[(j * cp.video.mode.screen->width + i) * 4 + 0] = r;
					buffer[(j * cp.video.mode.screen->width + i) * 4 + 1] = g;
					buffer[(j * cp.video.mode.screen->width + i) * 4 + 2] = b;
					buffer[(j * cp.video.mode.screen->width + i) * 4 + 3] = 0;
					break;
				}
				case 2:
				{
					SCR_GetPixelRGB16(i, j, &r, &g, &b);
					buffer[(j * cp.video.mode.screen->width + i) * 4 + 0] = r;
					buffer[(j * cp.video.mode.screen->width + i) * 4 + 1] = g;
					buffer[(j * cp.video.mode.screen->width + i) * 4 + 2] = b;
					buffer[(j * cp.video.mode.screen->width + i) * 4 + 3] = 0;
					break;
				}
				case 3:
				{
					SCR_GetPixelRGB24(i, j, &r, &g, &b);
					buffer[(j * cp.video.mode.screen->width + i) * 4 + 0] = r;
					buffer[(j * cp.video.mode.screen->width + i) * 4 + 1] = g;
					buffer[(j * cp.video.mode.screen->width + i) * 4 + 2] = b;
					buffer[(j * cp.video.mode.screen->width + i) * 4 + 3] = 0;
					break;
				}
				case 4:
				{
					SCR_GetPixelRGBA(i, j, &r, &g, &b, &a);
					buffer[(j * cp.video.mode.screen->width + i) * 4 + 0] = r;
					buffer[(j * cp.video.mode.screen->width + i) * 4 + 1] = g;
					buffer[(j * cp.video.mode.screen->width + i) * 4 + 2] = b;
					buffer[(j * cp.video.mode.screen->width + i) * 4 + 3] = a;
					break;
				}
			}
		}
	}
	mw = NewMagickWand();
	MagickConstituteImage(mw, cp.video.mode.screen->width, cp.video.mode.screen->height, "RGBO", CharPixel, buffer);
	free(buffer);
	MagickWriteImage(mw, image);
	DestroyMagickWand(mw);
}
